package com.dlc.shop.platform.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huifu.bspay.sdk.opps.core.request.V2TradePaymentDelaytransConfirmRequest;
import com.huifu.bspay.sdk.opps.core.utils.DateTools;
import com.huifu.bspay.sdk.opps.core.utils.SequenceTools;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.dlc.shop.bean.app.param.ProdCommParam;
import com.dlc.shop.bean.bo.OrderChangeShopWalletAmountBO;
import com.dlc.shop.bean.bo.PayInfoResultBO;
import com.dlc.shop.bean.enums.OrderStatus;
import com.dlc.shop.bean.enums.PayStatus;
import com.dlc.shop.bean.enums.SendType;
import com.dlc.shop.bean.model.*;
import com.dlc.shop.common.allinpay.constant.PaySysType;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.enums.PayType;
import com.dlc.shop.common.util.ExceptionUtils;
import com.dlc.shop.huifu.BaseCommonDemo;
import com.dlc.shop.huifu.DemoTestConstants;
import com.dlc.shop.huifu.OppsMerchantConfigDemo;
import com.dlc.shop.manager.impl.PayManager;
import com.dlc.shop.service.*;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static com.dlc.shop.huifu.BaseCommonDemo.doExecute;
import static com.dlc.shop.huifu.BaseCommonDemo.doInit;


/**
 * @author yami
 */
@Component
@AllArgsConstructor
public class OrderTask {


    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final OrderService orderService;
    private final OrderItemService orderItemService;
    private final NotifyTemplateService notifyTemplateService;
    private final ProductService productService;
    private final ProdCommService prodCommService;
    private final SkuService skuService;
    private final PayInfoService payInfoService;
    private final PayManager payManager;
    private final NotifyLogService notifyLogService;
    private final ShopDetailService shopDetailService;

    @XxlJob("cancelOrder")
    public void cancelOrder() {
        try {
            logger.info("解锁创建失败订单的库存。。。");
            orderService.unLockFailOrderStock();

            Date now = new Date();
            logger.info("取消超时未支付订单。。。");
            // 获取30分钟之前未支付的订单
            List<Order> orders = orderService.listUnRefundOrderAndOrderItems(OrderStatus.UNPAY.value(), DateUtil.offsetMinute(now, -30));
            if (CollectionUtil.isEmpty(orders)) {
                return;
            }
            List<Order> cancelOrderList = this.checkOrders(orders);
            orderService.cancelOrders(cancelOrderList);
            // 移除缓存
            this.removeCache(cancelOrderList);
        } catch (Exception e) {
            logger.info("未付款的订单超时处理失败：" + ExceptionUtils.getRunException(e));
        }
    }

    /**
     * 确认收货15天后执行订单结算
     */
    @XxlJob("orderCommissionSettlement")
    public void orderCommissionSettlement() throws Exception {
        logger.info("开始执行订单结算任务》》》》》》》》》》》》》》》》》》》》》");
        Date now = new Date();
        // 确认收货15天的订单，进行结算(更新时间为15天前的订单)
        List<Order> orders = orderService.listPendingSettlementOrders(OrderStatus.SUCCESS.value(), DateUtil.beginOfDay(DateUtil.offsetDay(now, -Constant.DISTRIBUTION_SETTLEMENT_TIME)));
        if (CollectionUtil.isEmpty(orders)) {
            return;
        }

        for (Order order : orders) {

            QueryWrapper<PayInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("pay_status", 1);
            queryWrapper.apply("FIND_IN_SET({0}, order_numbers) > 0", order.getOrderNumber());
            PayInfo payInfo = payInfoService.getOne(queryWrapper);
            //判断本次支付存在几个订单
            String[] orderNembers = payInfo.getOrderNumbers().split(",");
            Boolean isContinue = false;
            if (orderNembers.length > 1) {
                //分单订单，确认俩个订单 完成时间都 > 15天 在进行分账结算 同时记录订单已经结算
                //查询订单完成时间
                List<Order> orderList = orderService.getOrderPayInfoByOrderNumber(Arrays.asList(orderNembers));
                for (Order order1 : orderList) {
                    if (order1.getFinallyTime() == null) {
                        isContinue = true;
                    }
                    if (new Date().getTime() - order1.getFinallyTime().getTime() < 15 * 24 * 60 * 60 * 1000) {
                        isContinue = true;
                    }
                }
            }
            if (isContinue) {
                continue;
            }
            // 1. 数据初始化
            BaseCommonDemo.doInit(OppsMerchantConfigDemo.getMerchantConfig());
            // 2.组装请求参数
            V2TradePaymentDelaytransConfirmRequest request = new V2TradePaymentDelaytransConfirmRequest();
            // 请求日期
            request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
            // 请求流水号
            request.setReqSeqId(SequenceTools.getReqSeqId32());
            // 商户号
            request.setHuifuId(DemoTestConstants.DEMO_SYS_ID);

            // 设置非必填字段
            Map<String, Object> extendInfoMap = new HashMap<>();
            extendInfoMap.put("org_req_date", payInfo.getReqDate());
            extendInfoMap.put("org_req_seq_id", payInfo.getBizPayNo());
            extendInfoMap.put("acct_split_bunch", getAcctSplitBunch(order));
            request.setExtendInfo(extendInfoMap);
            // 3. 发起API调用
            Map<String, Object> response = BaseCommonDemo.doExecute(request);
            if (response.get("resp_code").toString().equals("00000000") && response.get("trans_stat").toString().equals("S")) {
                order.setIsSettled(1);
                orderService.updateById(order);
            }
        }

//        List<com.dlc.shop.bean.model.Order> normalOrderList = orders.stream().filter(order -> Objects.equals(order.getPaySysType(), PaySysType.DEFAULT.value())).toList();
//        List<com.dlc.shop.bean.model.Order> allinpayOrderList = orders.stream().filter(order -> Objects.equals(order.getPaySysType(), PaySysType.ALLINPAY.value())).toList();
//        if(CollectionUtil.isNotEmpty(normalOrderList)) {
//            orderService.orderCommissionSettlement(orders);
//            // 移除缓存
//            this.removeCache(orders);
//        }
//        if (CollUtil.isNotEmpty(allinpayOrderList)) {
//            for (com.dlc.shop.bean.model.Order order : allinpayOrderList) {
//                OrderChangeShopWalletAmountBO orderChangeShopWalletAmountBO = new OrderChangeShopWalletAmountBO();
//                orderChangeShopWalletAmountBO.setShopId(order.getShopId());
//                orderChangeShopWalletAmountBO.setOrderNumber(order.getOrderNumber());
//                orderService.doAllinPaySettlement(orderChangeShopWalletAmountBO);
//            }
//        }
        this.removeCache(orders);
        logger.info("结束执行订单结算任务》》》》》》》》》》》》》》》》》》》》》");
    }

    private String getAcctSplitBunch(Order order) {
        JSONObject dto = new JSONObject();
        // 分账明细
        dto.put("acct_infos", getAcctInfosRucan(order));

        return dto.toJSONString();
    }

    private JSON getAcctInfosRucan(Order order) {
        JSONObject dto = new JSONObject();
        double aDouble = 0d;
        List<OrderItem> orderItems = orderService.getOrderDetailByOrderNumberAndShopId(order.getOrderNumber(), order.getShopId()).getOrderItems();
        for (OrderItem orderItem : orderItems) {
            if (orderItem.getRefundId() != null) {
                continue;
            }
            Sku sku = skuService.getSkuBySkuId(orderItem.getSkuId());
            aDouble += (sku.getSupplierPrice() * orderItem.getProdCount());
        }
        ShopDetail shopDetail = shopDetailService.getById(order.getShopId());
        // 分账金额
        dto.put("div_amt", BigDecimal.valueOf(aDouble).setScale(2, RoundingMode.HALF_UP));
        // 分账接收方ID
        dto.put("huifu_id", shopDetail.getHuifuId());

        JSONArray dtoList = new JSONArray();
        dtoList.add(dto);
        if (!shopDetail.getHuifuId().equals(DemoTestConstants.DEMO_SYS_ID)) {
            JSONObject dto1 = new JSONObject();
            dto1.put("div_amt", BigDecimal.valueOf(order.getActualTotal() - aDouble).setScale(2, RoundingMode.HALF_UP));
            // 分账接收方ID
            dto1.put("huifu_id", DemoTestConstants.DEMO_SYS_ID);
            dtoList.add(dto1);
        }
        return dtoList;
    }

    /**
     * 订单催付提醒,每1分钟执行发送一次订单未支付的提醒
     */
    @XxlJob("pressPayOrder")
    public void pressPayOrder() {
        Date now = new Date();
        logger.info("执行订单催付提醒");
        // 获取15分钟之前未支付的订单
        List<Order> orders = orderService.listUnRefundOrderAndOrderItems(OrderStatus.UNPAY.value(), DateUtil.offsetMinute(now, -15));
        if (CollectionUtil.isEmpty(orders)) {
            return;
        }
        // 消息推送-订单催付提醒
        // 对相同用户id进行去重
        orders = orders.stream().filter(distinctByKey(Order::getUserId)).collect(Collectors.toList());
        for (Order order : orders) {
            Integer num = notifyLogService.countMsgNum(order.getOrderNumber());
            if (num < 1) {
                //没发过催付消息才会发送
                notifyTemplateService.sendNotifyOfDelivery(order, null, SendType.PRESS_PAY);
            }
        }
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    /**
     * 确认收货
     */
    @XxlJob("confirmOrder")
    public void confirmOrder() {
        Date now = new Date();
        logger.info("系统自动确认收货订单。。。");
        // 获取15天之前等待确认收货的订单
        List<Order> orders = orderService.listUnRefundOrderAndOrderItems(OrderStatus.CONSIGNMENT.value(), DateUtil.offsetDay(now, -15));
        // 获取核销时间超出当前时间的，已支付但未完成的虚拟订单
        List<Order> overdueOrders = orderService.list(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderMold, 1)
                .eq(Order::getIsPayed, 1)
                .notIn(Order::getStatus, OrderStatus.SUCCESS.value(), OrderStatus.CLOSE.value())
                .lt(Order::getWriteOffEnd, new Date()));
        orders.addAll(overdueOrders);
        if (CollectionUtil.isEmpty(orders)) {
            return;
        }
        orderService.receiptOrder(orders);
        // 移除缓存
        this.removeCache(orders);
    }

    /**
     * 自动商品好评（确认收货30天，未进行评论，自动默认5星好评）
     */
    @XxlJob("autoProdGoodComm")
    public void autoProdGoodComm() {
        logger.info("确认收货30天，自动好评...");
        Date now = new Date();
        DateTime endTime = DateUtil.offsetDay(now, -30);
        List<OrderItem> orderItems = orderItemService.listUnCommOrderItem(endTime);
        if (CollectionUtil.isEmpty(orderItems)) {
            return;
        }
        List<ProdCommParam> prodCommParams = new ArrayList<>(orderItems.size());
        for (int i = 0; i < orderItems.size(); i++) {
            ProdCommParam prodCommParam = new ProdCommParam();
            prodCommParam.setScore(5);
            prodCommParam.setIsAnonymous(1);
            prodCommParam.setRecTime(now);
            prodCommParams.add(prodCommParam);
        }
        prodCommService.saveBatchComm(orderItems, prodCommParams);
    }

    /**
     * 查询订单，去除已支付的订单
     *
     * @param orders
     */
    private List<Order> checkOrders(List<Order> orders) {
        // 收集未支付的订单
        List<Order> orderList = new ArrayList<>();
        for (Order order : orders) {
            // 获取支付过的信息
            List<PayInfo> payInfoList = payInfoService.list(new LambdaQueryWrapper<PayInfo>().like(PayInfo::getOrderNumbers, order.getOrderNumber()));
            if (CollectionUtil.isEmpty(payInfoList)) {
                orderList.add(order);
                continue;
            }
            boolean unPay = true;
            for (PayInfo payInfo : payInfoList) {
                String bizPayNo = null;
                if (Objects.nonNull(payInfo.getPayNo())) {
                    bizPayNo = payInfo.getBizPayNo();
                }
                PayInfoResultBO payInfoResultBO = payManager.getPayHuiFuInfo(PayType.instance(payInfo.getPayType()),
                        payInfo.getPayNo(), payInfo.getPaySysType(), bizPayNo, payInfo.getReqDate());
                // 如果之前是已经支付成功过的，直接更新订单
                if (payInfoResultBO.getIsPaySuccess()) {
                    // 根据内部订单号更新order settlement
                    if (Objects.equals(payInfo.getPayStatus(), PayStatus.UNPAY.value())) {
                        payInfoService.noticeOrder(payInfoResultBO, payInfo, payInfoResultBO.getPaySysType());
                    }
                    unPay = false;
                    break;
                }
            }
            // 没有支付过就直接取消订单
            if (unPay) {
                orderList.add(order);
            }
        }
        return orderList;
    }

    /**
     * 移除缓存
     */
    private void removeCache(List<Order> orders) {
        for (Order order : orders) {
            List<OrderItem> orderItems = order.getOrderItems();
            for (OrderItem orderItem : orderItems) {
                productService.removeProdCacheByProdId(orderItem.getProdId());
                skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
            }
        }
    }
}
